// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.network;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import zombie.characters.IsoPlayer;
import zombie.characters.IsoZombie;
import zombie.core.Rand;
import zombie.core.logger.LoggerManager;
import zombie.core.network.ByteBufferWriter;
import zombie.core.raknet.UdpConnection;
import zombie.core.stash.StashSystem;
import zombie.core.utils.OnceEvery;
import zombie.core.znet.SteamUtils;
import zombie.debug.DebugLog;
import zombie.debug.DebugType;
import zombie.globalObjects.SGlobalObjects;
import zombie.iso.IsoChunk;
import zombie.iso.IsoGridSquare;
import zombie.iso.IsoMetaGrid;
import zombie.iso.IsoUtils;
import zombie.iso.IsoWorld;
import zombie.iso.RoomDef;
import zombie.iso.Vector2;
import zombie.iso.Vector3;
import zombie.popman.NetworkZombiePacker;
import zombie.popman.ZombiePopulationManager;
import zombie.radio.ZomboidRadio;
import zombie.savefile.ServerPlayerDB;
import zombie.vehicles.BaseVehicle;
import zombie.vehicles.VehiclesDB2;
import zombie.world.moddata.GlobalModData;

public class ServerMap {
    public boolean bUpdateLOSThisFrame = false;
    public static OnceEvery LOSTick = new OnceEvery(1.0F);
    public static OnceEvery TimeTick = new OnceEvery(600.0F);
    public static final int CellSize = 50;
    public static final int ChunksPerCellWidth = 5;
    public long LastSaved = 0L;
    private static boolean MapLoading;
    public final IsoObjectID<IsoZombie> ZombieMap = new IsoObjectID<>(IsoZombie.class);
    public boolean bQueuedSaveAll = false;
    public boolean bQueuedQuit = false;
    public static ServerMap instance = new ServerMap();
    public ServerMap.ServerCell[] cellMap;
    public ArrayList<ServerMap.ServerCell> LoadedCells = new ArrayList();
    public ArrayList<ServerMap.ServerCell> ReleventNow = new ArrayList();
    int width;
    int height;
    IsoMetaGrid grid;
    ArrayList<ServerMap.ServerCell> ToLoad = new ArrayList();
    static final ServerMap.DistToCellComparator distToCellComparator = new ServerMap.DistToCellComparator();
    private final ArrayList<ServerMap.ServerCell> tempCells = new ArrayList();
    long lastTick = 0L;
    Vector2 start;

    public short getUniqueZombieId() {
        return this.ZombieMap.allocateID();
    }

    public Vector3 getStartLocation(ServerWorldDatabase.LogonResult r) {
        short short0 = 9412;
        short short1 = 10745;
        byte _byte = 0;
        return new Vector3((float)short1, (float)short0, (float)_byte);
    }

    public void SaveAll() {
        long _long = System.nanoTime();

        for (int _int = 0; _int < this.LoadedCells.size(); _int++) {
            ((ServerMap.ServerCell)this.LoadedCells.get(_int)).Save();
        }

        this.grid.save();
        DebugLog.log("SaveAll took " + (double)(System.nanoTime() - _long) / 1000000.0 + " ms");
    }

    public void QueueSaveAll() {
        this.bQueuedSaveAll = true;
    }

    public void QueueQuit() {
        DebugLog.Multiplayer.printStackTrace();
        this.bQueuedSaveAll = true;
        this.bQueuedQuit = true;
    }

    public int toServerCellX(int x) {
        x *= 300;
        return x / 50;
    }

    public int toServerCellY(int y) {
        y *= 300;
        return y / 50;
    }

    public int toWorldCellX(int x) {
        x *= 50;
        return x / 300;
    }

    public int toWorldCellY(int y) {
        y *= 50;
        return y / 300;
    }

    public int getMaxX() {
        int _int = this.toServerCellX(this.grid.maxX + 1);
        if ((this.grid.maxX + 1) * 300 % 50 == 0) {
            _int--;
        }

        return _int;
    }

    public int getMaxY() {
        int _int = this.toServerCellY(this.grid.maxY + 1);
        if ((this.grid.maxY + 1) * 300 % 50 == 0) {
            _int--;
        }

        return _int;
    }

    public int getMinX() {
        return this.toServerCellX(this.grid.minX);
    }

    public int getMinY() {
        return this.toServerCellY(this.grid.minY);
    }

    public void init(IsoMetaGrid metaGrid) {
        this.grid = metaGrid;
        this.width = this.getMaxX() - this.getMinX() + 1;
        this.height = this.getMaxY() - this.getMinY() + 1;

        assert this.width * 50 >= metaGrid.getWidth() * 300;

        assert this.height * 50 >= metaGrid.getHeight() * 300;

        assert this.getMaxX() * 50 < (metaGrid.getMaxX() + 1) * 300;

        assert this.getMaxY() * 50 < (metaGrid.getMaxY() + 1) * 300;

        int _int = this.width * this.height;
        this.cellMap = new ServerMap.ServerCell[_int];
        StashSystem.init();
    }

    public ServerMap.ServerCell getCell(int x, int y) {
        return !this.isValidCell(x, y) ? null : this.cellMap[y * this.width + x];
    }

    public boolean isValidCell(int x, int y) {
        return x >= 0 && y >= 0 && x < this.width && y < this.height;
    }

    public void loadOrKeepRelevent(int x, int y) {
        if (this.isValidCell(x, y)) {
            ServerMap.ServerCell serverCell = this.getCell(x, y);
            if (serverCell == null) {
                serverCell = new ServerMap.ServerCell();
                serverCell.WX = x + this.getMinX();
                serverCell.WY = y + this.getMinY();
                if (MapLoading) {
                    DebugLog.log(
                        DebugType.MapLoading,
                        "Loading cell: "
                            + serverCell.WX
                            + ", "
                            + serverCell.WY
                            + " ("
                            + this.toWorldCellX(serverCell.WX)
                            + ", "
                            + this.toWorldCellX(serverCell.WY)
                            + ")"
                    );
                }

                this.cellMap[y * this.width + x] = serverCell;
                this.ToLoad.add(serverCell);
                MPStatistic.getInstance().ServerMapToLoad.Added();
                this.LoadedCells.add(serverCell);
                MPStatistic.getInstance().ServerMapLoadedCells.Added();
                this.ReleventNow.add(serverCell);
            } else if (!this.ReleventNow.contains(serverCell)) {
                this.ReleventNow.add(serverCell);
            }
        }
    }

    public void characterIn(IsoPlayer p) {
        while (this.grid == null) {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        }

        int int0 = p.OnlineChunkGridWidth / 2 * 10;
        int int1 = (int)(Math.floor((double)((p.getX() - (float)int0) / 50.0F)) - (double)this.getMinX());
        int int2 = (int)(Math.floor((double)((p.getX() + (float)int0) / 50.0F)) - (double)this.getMinX());
        int int3 = (int)(Math.floor((double)((p.getY() - (float)int0) / 50.0F)) - (double)this.getMinY());
        int int4 = (int)(Math.floor((double)((p.getY() + (float)int0) / 50.0F)) - (double)this.getMinY());

        for (int int5 = int3; int5 <= int4; int5++) {
            for (int int6 = int1; int6 <= int2; int6++) {
                this.loadOrKeepRelevent(int6, int5);
            }
        }
    }

    public void characterIn(int wx, int wy, int chunkGridWidth) {
        while (this.grid == null) {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        }

        int int0 = wx * 10;
        int int1 = wy * 10;
        int0 = (int)((float)int0 / 50.0F);
        int1 = (int)((float)int1 / 50.0F);
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        int int2 = wx * 10 % 50;
        int int3 = wy * 10 % 50;
        int int4 = chunkGridWidth / 2 * 10;
        int int5 = int0;
        int int6 = int1;
        int int7 = int0;
        int int8 = int1;
        if (int2 < int4) {
            int5 = int0 - 1;
        }

        if (int2 > 50 - int4) {
            int7 = int0 + 1;
        }

        if (int3 < int4) {
            int6 = int1 - 1;
        }

        if (int3 > 50 - int4) {
            int8 = int1 + 1;
        }

        for (int int9 = int6; int9 <= int8; int9++) {
            for (int int10 = int5; int10 <= int7; int10++) {
                this.loadOrKeepRelevent(int10, int9);
            }
        }
    }

    public void loadMapChunk(int ix, int iy) {
        while (this.grid == null) {
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }
        }

        int int0 = (int)((float)ix / 50.0F);
        int int1 = (int)((float)iy / 50.0F);
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        this.loadOrKeepRelevent(int0, int1);
    }

    public void preupdate() {
        long long0 = System.nanoTime();
        long long1 = long0 - this.lastTick;
        double _double = (double)long1 * 1.0E-6;
        this.lastTick = long0;
        MapLoading = DebugType.Do(DebugType.MapLoading);

        for (int int0 = 0; int0 < this.ToLoad.size(); int0++) {
            ServerMap.ServerCell serverCell0 = (ServerMap.ServerCell)this.ToLoad.get(int0);
            if (serverCell0.bLoadingWasCancelled) {
                if (MapLoading) {
                    DebugLog.log(DebugType.MapLoading, "MainThread: forgetting cancelled " + serverCell0.WX + "," + serverCell0.WY);
                }

                int int1 = serverCell0.WX - this.getMinX();
                int int2 = serverCell0.WY - this.getMinY();

                assert this.cellMap[int1 + int2 * this.width] == serverCell0;

                this.cellMap[int1 + int2 * this.width] = null;
                this.LoadedCells.remove(serverCell0);
                this.ReleventNow.remove(serverCell0);
                ServerMap.ServerCell.loaded2.remove(serverCell0);
                this.ToLoad.remove(int0--);
                MPStatistic.getInstance().ServerMapToLoad.Canceled();
            }
        }

        for (int int3 = 0; int3 < this.LoadedCells.size(); int3++) {
            ServerMap.ServerCell serverCell1 = (ServerMap.ServerCell)this.LoadedCells.get(int3);
            if (serverCell1.bCancelLoading) {
                if (MapLoading) {
                    DebugLog.log(DebugType.MapLoading, "MainThread: forgetting cancelled " + serverCell1.WX + "," + serverCell1.WY);
                }

                int int4 = serverCell1.WX - this.getMinX();
                int int5 = serverCell1.WY - this.getMinY();

                assert this.cellMap[int4 + int5 * this.width] == serverCell1;

                this.cellMap[int4 + int5 * this.width] = null;
                this.LoadedCells.remove(int3--);
                this.ReleventNow.remove(serverCell1);
                ServerMap.ServerCell.loaded2.remove(serverCell1);
                this.ToLoad.remove(serverCell1);
                MPStatistic.getInstance().ServerMapLoadedCells.Canceled();
            }
        }

        for (int int6 = 0; int6 < ServerMap.ServerCell.loaded2.size(); int6++) {
            ServerMap.ServerCell serverCell2 = (ServerMap.ServerCell)ServerMap.ServerCell.loaded2.get(int6);
            if (serverCell2.bCancelLoading) {
                if (MapLoading) {
                    DebugLog.log(DebugType.MapLoading, "MainThread: forgetting cancelled " + serverCell2.WX + "," + serverCell2.WY);
                }

                int int7 = serverCell2.WX - this.getMinX();
                int int8 = serverCell2.WY - this.getMinY();

                assert this.cellMap[int7 + int8 * this.width] == serverCell2;

                this.cellMap[int7 + int8 * this.width] = null;
                this.LoadedCells.remove(serverCell2);
                this.ReleventNow.remove(serverCell2);
                ServerMap.ServerCell.loaded2.remove(serverCell2);
                this.ToLoad.remove(serverCell2);
                MPStatistic.getInstance().ServerMapLoaded2.Canceled();
            }
        }

        if (!this.ToLoad.isEmpty()) {
            this.tempCells.clear();

            for (int int9 = 0; int9 < this.ToLoad.size(); int9++) {
                ServerMap.ServerCell serverCell3 = (ServerMap.ServerCell)this.ToLoad.get(int9);
                if (!serverCell3.bCancelLoading && !serverCell3.startedLoading) {
                    this.tempCells.add(serverCell3);
                }
            }

            if (!this.tempCells.isEmpty()) {
                distToCellComparator.init();
                Collections.sort(this.tempCells, distToCellComparator);

                for (int int10 = 0; int10 < this.tempCells.size(); int10++) {
                    ServerMap.ServerCell serverCell4 = (ServerMap.ServerCell)this.tempCells.get(int10);
                    ServerMap.ServerCell.chunkLoader.addJob(serverCell4);
                    serverCell4.startedLoading = true;
                }
            }

            ServerMap.ServerCell.chunkLoader.getLoaded(ServerMap.ServerCell.loaded);

            for (int int11 = 0; int11 < ServerMap.ServerCell.loaded.size(); int11++) {
                ServerMap.ServerCell serverCell5 = (ServerMap.ServerCell)ServerMap.ServerCell.loaded.get(int11);
                if (!serverCell5.doingRecalc) {
                    ServerMap.ServerCell.chunkLoader.addRecalcJob(serverCell5);
                    serverCell5.doingRecalc = true;
                }
            }

            ServerMap.ServerCell.loaded.clear();
            ServerMap.ServerCell.chunkLoader.getRecalc(ServerMap.ServerCell.loaded2);
            if (!ServerMap.ServerCell.loaded2.isEmpty()) {
                try {
                    ServerLOS.instance.suspend();

                    for (int int12 = 0; int12 < ServerMap.ServerCell.loaded2.size(); int12++) {
                        ServerMap.ServerCell serverCell6 = (ServerMap.ServerCell)ServerMap.ServerCell.loaded2.get(int12);
                        long long2 = System.nanoTime();
                        if (serverCell6.Load2()) {
                            long2 = System.nanoTime();
                            int12--;
                            this.ToLoad.remove(serverCell6);
                        }
                    }
                } finally {
                    ServerLOS.instance.resume();
                }
            }
        }

        int int13 = ServerOptions.instance.SaveWorldEveryMinutes.getValue();
        if (int13 > 0) {
            long long3 = System.currentTimeMillis();
            if (long3 > this.LastSaved + (long)(int13 * 60 * 1000)) {
                this.bQueuedSaveAll = true;
                this.LastSaved = long3;
            }
        }

        if (this.bQueuedSaveAll) {
            this.bQueuedSaveAll = false;
            long long4 = System.nanoTime();
            this.SaveAll();
            ServerMap.ServerCell.chunkLoader.saveLater(zombie.GameTime.instance);
            zombie.ReanimatedPlayers.instance.saveReanimatedPlayers();
            zombie.MapCollisionData.instance.save();
            SGlobalObjects.save();

            try {
                ZomboidRadio.getInstance().Save();
            } catch (Exception exception0) {
                exception0.printStackTrace();
            }

            try {
                GlobalModData.instance.save();
            } catch (Exception exception1) {
                exception1.printStackTrace();
            }

            GameServer.UnPauseAllClients();
            System.out.println("Saving finish");
            DebugLog.log("Saving took " + (double)(System.nanoTime() - long4) / 1000000.0 + " ms");
        }

        if (this.bQueuedQuit) {
            ByteBufferWriter byteBufferWriter = GameServer.udpEngine.startPacket();
            PacketTypes.PacketType.ServerQuit.doPacket(byteBufferWriter);
            GameServer.udpEngine.endPacketBroadcast(PacketTypes.PacketType.ServerQuit);

            try {
                Thread.sleep(5000L);
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }

            zombie.MapCollisionData.instance.stop();
            ZombiePopulationManager.instance.stop();
            RCONServer.shutdown();
            ServerMap.ServerCell.chunkLoader.quit();
            ServerWorldDatabase.instance.close();
            ServerPlayersVehicles.instance.stop();
            ServerPlayerDB.getInstance().close();
            VehiclesDB2.instance.Reset();
            GameServer.udpEngine.Shutdown();
            ServerGUI.shutdown();
            SteamUtils.shutdown();
            System.exit(0);
        }

        this.ReleventNow.clear();
        this.bUpdateLOSThisFrame = LOSTick.Check();
        if (TimeTick.Check()) {
            ServerMap.ServerCell.chunkLoader.saveLater(zombie.GameTime.instance);
        }
    }

    private IsoGridSquare getRandomSquareFromCell(int int0, int int1) {
        this.loadOrKeepRelevent(int0, int1);
        int int2 = int0;
        int int3 = int1;
        ServerMap.ServerCell serverCell = this.getCell(int0, int1);
        if (serverCell == null) {
            throw new RuntimeException("Cannot find a random square.");
        } else {
            int0 = (int0 + this.getMinX()) * 50;
            int1 = (int1 + this.getMinY()) * 50;
            IsoGridSquare isoGridSquare = null;
            int int4 = 100;

            do {
                isoGridSquare = this.getGridSquare(Rand.Next(int0, int0 + 50), Rand.Next(int1, int1 + 50), 0);
                int4--;
                if (isoGridSquare == null) {
                    this.loadOrKeepRelevent(int2, int3);
                }
            } while (isoGridSquare == null && int4 > 0);

            return isoGridSquare;
        }
    }

    public void postupdate() {
        int int0 = this.LoadedCells.size();
        boolean boolean0 = false;

        try {
            for (int int1 = 0; int1 < this.LoadedCells.size(); int1++) {
                ServerMap.ServerCell serverCell = (ServerMap.ServerCell)this.LoadedCells.get(int1);
                boolean boolean1 = this.ReleventNow.contains(serverCell) || !this.outsidePlayerInfluence(serverCell);
                if (!serverCell.bLoaded) {
                    if (!boolean1 && !serverCell.bCancelLoading) {
                        if (MapLoading) {
                            DebugLog.log(
                                DebugType.MapLoading,
                                "MainThread: cancelling " + serverCell.WX + "," + serverCell.WY + " cell.startedLoading=" + serverCell.startedLoading
                            );
                        }

                        if (!serverCell.startedLoading) {
                            serverCell.bLoadingWasCancelled = true;
                        }

                        serverCell.bCancelLoading = true;
                    }
                } else if (!boolean1) {
                    int int2 = serverCell.WX - this.getMinX();
                    int int3 = serverCell.WY - this.getMinY();
                    if (!boolean0) {
                        ServerLOS.instance.suspend();
                        boolean0 = true;
                    }

                    this.cellMap[int3 * this.width + int2].Unload();
                    this.cellMap[int3 * this.width + int2] = null;
                    this.LoadedCells.remove(serverCell);
                    int1--;
                } else {
                    serverCell.update();
                }
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            if (boolean0) {
                ServerLOS.instance.resume();
            }
        }

        NetworkZombiePacker.getInstance().postupdate();
        ServerMap.ServerCell.chunkLoader.updateSaved();
    }

    public void physicsCheck(int x, int y) {
        int int0 = x / 50;
        int int1 = y / 50;
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        ServerMap.ServerCell serverCell = this.getCell(int0, int1);
        if (serverCell != null && serverCell.bLoaded) {
            serverCell.bPhysicsCheck = true;
        }
    }

    private boolean outsidePlayerInfluence(ServerMap.ServerCell serverCell) {
        int int0 = serverCell.WX * 50;
        int int1 = serverCell.WY * 50;
        int int2 = (serverCell.WX + 1) * 50;
        int int3 = (serverCell.WY + 1) * 50;

        for (int int4 = 0; int4 < GameServer.udpEngine.connections.size(); int4++) {
            UdpConnection udpConnection = (UdpConnection)GameServer.udpEngine.connections.get(int4);
            if (udpConnection.RelevantTo((float)int0, (float)int1)) {
                return false;
            }

            if (udpConnection.RelevantTo((float)int2, (float)int1)) {
                return false;
            }

            if (udpConnection.RelevantTo((float)int2, (float)int3)) {
                return false;
            }

            if (udpConnection.RelevantTo((float)int0, (float)int3)) {
                return false;
            }
        }

        return true;
    }

    public void saveZoneInsidePlayerInfluence(short playerOID) {
        for (int int0 = 0; int0 < GameServer.udpEngine.connections.size(); int0++) {
            UdpConnection udpConnection = (UdpConnection)GameServer.udpEngine.connections.get(int0);

            for (int int1 = 0; int1 < udpConnection.players.length; int1++) {
                if (udpConnection.players[int1] != null && udpConnection.players[int1].OnlineID == playerOID) {
                    IsoGridSquare isoGridSquare = IsoWorld.instance
                        .CurrentCell
                        .getGridSquare((double)udpConnection.players[int1].x, (double)udpConnection.players[int1].y, (double)udpConnection.players[int1].z);
                    if (isoGridSquare != null) {
                        ServerMap.ServerCell.chunkLoader.addSaveLoadedJob(isoGridSquare.chunk);
                        return;
                    }
                }
            }
        }

        ServerMap.ServerCell.chunkLoader.updateSaved();
    }

    private boolean InsideThePlayerInfluence(ServerMap.ServerCell serverCell, short _short) {
        int int0 = serverCell.WX * 50;
        int int1 = serverCell.WY * 50;
        int int2 = (serverCell.WX + 1) * 50;
        int int3 = (serverCell.WY + 1) * 50;

        for (int int4 = 0; int4 < GameServer.udpEngine.connections.size(); int4++) {
            UdpConnection udpConnection = (UdpConnection)GameServer.udpEngine.connections.get(int4);

            for (int int5 = 0; int5 < udpConnection.players.length; int5++) {
                if (udpConnection.players[int5] != null && udpConnection.players[int5].OnlineID == _short) {
                    if (udpConnection.RelevantToPlayerIndex(int5, (float)int0, (float)int1)) {
                        return true;
                    }

                    if (udpConnection.RelevantToPlayerIndex(int5, (float)int2, (float)int1)) {
                        return true;
                    }

                    if (udpConnection.RelevantToPlayerIndex(int5, (float)int2, (float)int3)) {
                        return true;
                    }

                    if (udpConnection.RelevantToPlayerIndex(int5, (float)int0, (float)int3)) {
                        return true;
                    }

                    return false;
                }
            }
        }

        return false;
    }

    public IsoGridSquare getGridSquare(int x, int y, int z) {
        if (!IsoWorld.instance.isValidSquare(x, y, z)) {
            return null;
        } else {
            int int0 = x / 50;
            int int1 = y / 50;
            int0 -= this.getMinX();
            int1 -= this.getMinY();
            int int2 = x / 10;
            int int3 = y / 10;
            int int4 = int2 % 5;
            int int5 = int3 % 5;
            int int6 = x % 10;
            int int7 = y % 10;
            ServerMap.ServerCell serverCell = this.getCell(int0, int1);
            if (serverCell != null && serverCell.bLoaded) {
                IsoChunk isoChunk = serverCell.chunks[int4][int5];
                return isoChunk == null ? null : isoChunk.getGridSquare(int6, int7, z);
            } else {
                return null;
            }
        }
    }

    public void setGridSquare(int x, int y, int z, IsoGridSquare sq) {
        int int0 = x / 50;
        int int1 = y / 50;
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        int int2 = x / 10;
        int int3 = y / 10;
        int int4 = int2 % 5;
        int int5 = int3 % 5;
        int int6 = x % 10;
        int int7 = y % 10;
        ServerMap.ServerCell serverCell = this.getCell(int0, int1);
        if (serverCell != null) {
            IsoChunk isoChunk = serverCell.chunks[int4][int5];
            if (isoChunk != null) {
                isoChunk.setSquare(int6, int7, z, sq);
            }
        }
    }

    public boolean isInLoaded(float x, float y) {
        int int0 = (int)x;
        int int1 = (int)y;
        int0 /= 50;
        int1 /= 50;
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        return this.ToLoad.contains(this.getCell(int0, int1)) ? false : this.getCell(int0, int1) != null;
    }

    public IsoChunk getChunk(int wx, int wy) {
        if (wx >= 0 && wy >= 0) {
            int int0 = wx / 5;
            int int1 = wy / 5;
            int0 -= this.getMinX();
            int1 -= this.getMinY();
            int int2 = wx % 5;
            int int3 = wy % 5;
            ServerMap.ServerCell serverCell = this.getCell(int0, int1);
            return serverCell != null && serverCell.bLoaded ? serverCell.chunks[int2][int3] : null;
        } else {
            return null;
        }
    }

    public void setSoftResetChunk(IsoChunk chunk) {
        int int0 = chunk.wx / 5;
        int int1 = chunk.wy / 5;
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        if (this.isValidCell(int0, int1)) {
            ServerMap.ServerCell serverCell = this.getCell(int0, int1);
            if (serverCell == null) {
                serverCell = new ServerMap.ServerCell();
                serverCell.bLoaded = true;
                this.cellMap[int1 * this.width + int0] = serverCell;
            }

            int int2 = chunk.wx % 5;
            int int3 = chunk.wy % 5;
            serverCell.chunks[int2][int3] = chunk;
        }
    }

    public void clearSoftResetChunk(IsoChunk chunk) {
        int int0 = chunk.wx / 5;
        int int1 = chunk.wy / 5;
        int0 -= this.getMinX();
        int1 -= this.getMinY();
        ServerMap.ServerCell serverCell = this.getCell(int0, int1);
        if (serverCell != null) {
            int int2 = chunk.wx % 5;
            int int3 = chunk.wy % 5;
            serverCell.chunks[int2][int3] = null;
        }
    }

    private static class DistToCellComparator implements Comparator<ServerMap.ServerCell> {
        private Vector2[] pos = new Vector2[1024];
        private int posCount;

        public DistToCellComparator() {
            for (int _int = 0; _int < this.pos.length; _int++) {
                this.pos[_int] = new Vector2();
            }
        }

        public void init() {
            this.posCount = 0;

            for (int int0 = 0; int0 < GameServer.udpEngine.connections.size(); int0++) {
                UdpConnection udpConnection = (UdpConnection)GameServer.udpEngine.connections.get(int0);
                if (udpConnection.isFullyConnected()) {
                    for (int int1 = 0; int1 < 4; int1++) {
                        if (udpConnection.players[int1] != null) {
                            this.pos[this.posCount].set(udpConnection.players[int1].x, udpConnection.players[int1].y);
                            this.posCount++;
                        }
                    }
                }
            }
        }

        public int compare(ServerMap.ServerCell serverCell0, ServerMap.ServerCell serverCell1) {
            float float0 = Float.MAX_VALUE;
            float float1 = Float.MAX_VALUE;

            for (int _int = 0; _int < this.posCount; _int++) {
                float float2 = this.pos[_int].x;
                float float3 = this.pos[_int].y;
                float0 = Math.min(float0, this.distToCell(float2, float3, serverCell0));
                float1 = Math.min(float1, this.distToCell(float2, float3, serverCell1));
            }

            if (float0 < float1) {
                return -1;
            } else {
                return float0 > float1 ? 1 : 0;
            }
        }

        private float distToCell(float float1, float float3, ServerMap.ServerCell serverCell) {
            int int0 = serverCell.WX * 50;
            int int1 = serverCell.WY * 50;
            int int2 = int0 + 50;
            int int3 = int1 + 50;
            float float0 = float1;
            float float2 = float3;
            if (float1 < (float)int0) {
                float0 = (float)int0;
            } else if (float1 > (float)int2) {
                float0 = (float)int2;
            }

            if (float3 < (float)int1) {
                float2 = (float)int1;
            } else if (float3 > (float)int3) {
                float2 = (float)int3;
            }

            return IsoUtils.DistanceToSquared(float1, float3, float0, float2);
        }
    }

    public static class ServerCell {
        public int WX;
        public int WY;
        public boolean bLoaded = false;
        public boolean bPhysicsCheck = false;
        public final IsoChunk[][] chunks = new IsoChunk[5][5];
        private final HashSet<RoomDef> UnexploredRooms = new HashSet();
        private static final ServerChunkLoader chunkLoader = new ServerChunkLoader();
        private static final ArrayList<ServerMap.ServerCell> loaded = new ArrayList();
        private boolean startedLoading = false;
        public boolean bCancelLoading = false;
        public boolean bLoadingWasCancelled = false;
        private static final ArrayList<ServerMap.ServerCell> loaded2 = new ArrayList();
        private boolean doingRecalc = false;

        public boolean Load2() {
            chunkLoader.getRecalc(loaded2);

            for (int _int = 0; _int < loaded2.size(); _int++) {
                if (loaded2.get(_int) == this) {
                    long _long = System.nanoTime();
                    this.RecalcAll2();
                    loaded2.remove(_int);
                    if (ServerMap.MapLoading) {
                        DebugLog.log(DebugType.MapLoading, "loaded2=" + loaded2);
                    }

                    float _float = (float)(System.nanoTime() - _long) / 1000000.0F;
                    if (ServerMap.MapLoading) {
                        DebugLog.log(DebugType.MapLoading, "finish loading cell " + this.WX + "," + this.WY + " ms=" + _float);
                    }

                    this.loadVehicles();
                    return true;
                }
            }

            return false;
        }

        private void loadVehicles() {
            for (int int0 = 0; int0 < 5; int0++) {
                for (int int1 = 0; int1 < 5; int1++) {
                    IsoChunk isoChunk = this.chunks[int0][int1];
                    if (isoChunk != null && !isoChunk.isNewChunk()) {
                        VehiclesDB2.instance.loadChunkMain(isoChunk);
                    }
                }
            }
        }

        public void RecalcAll2() {
            int int0 = this.WX * 5 * 10;
            int int1 = this.WY * 5 * 10;
            int int2 = int0 + 50;
            int int3 = int1 + 50;

            for (RoomDef roomDef0 : this.UnexploredRooms) {
                roomDef0.IndoorZombies--;
            }

            this.UnexploredRooms.clear();
            this.bLoaded = true;

            for (int int4 = 1; int4 < 8; int4++) {
                for (int int5 = -1; int5 < 51; int5++) {
                    IsoGridSquare isoGridSquare0 = ServerMap.instance.getGridSquare(int0 + int5, int1 - 1, int4);
                    if (isoGridSquare0 != null && !isoGridSquare0.getObjects().isEmpty()) {
                        IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare0.x, isoGridSquare0.y, int4);
                    } else if (int5 >= 0 && int5 < 50) {
                        isoGridSquare0 = ServerMap.instance.getGridSquare(int0 + int5, int1, int4);
                        if (isoGridSquare0 != null && !isoGridSquare0.getObjects().isEmpty()) {
                            IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare0.x, isoGridSquare0.y, int4);
                        }
                    }

                    isoGridSquare0 = ServerMap.instance.getGridSquare(int0 + int5, int1 + 50, int4);
                    if (isoGridSquare0 != null && !isoGridSquare0.getObjects().isEmpty()) {
                        IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare0.x, isoGridSquare0.y, int4);
                    } else if (int5 >= 0 && int5 < 50) {
                        ServerMap.instance.getGridSquare(int0 + int5, int1 + 50 - 1, int4);
                        if (isoGridSquare0 != null && !isoGridSquare0.getObjects().isEmpty()) {
                            IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare0.x, isoGridSquare0.y, int4);
                        }
                    }
                }

                for (int int6 = 0; int6 < 50; int6++) {
                    IsoGridSquare isoGridSquare1 = ServerMap.instance.getGridSquare(int0 - 1, int1 + int6, int4);
                    if (isoGridSquare1 != null && !isoGridSquare1.getObjects().isEmpty()) {
                        IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare1.x, isoGridSquare1.y, int4);
                    } else {
                        isoGridSquare1 = ServerMap.instance.getGridSquare(int0, int1 + int6, int4);
                        if (isoGridSquare1 != null && !isoGridSquare1.getObjects().isEmpty()) {
                            IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare1.x, isoGridSquare1.y, int4);
                        }
                    }

                    isoGridSquare1 = ServerMap.instance.getGridSquare(int0 + 50, int1 + int6, int4);
                    if (isoGridSquare1 != null && !isoGridSquare1.getObjects().isEmpty()) {
                        IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare1.x, isoGridSquare1.y, int4);
                    } else {
                        isoGridSquare1 = ServerMap.instance.getGridSquare(int0 + 50 - 1, int1 + int6, int4);
                        if (isoGridSquare1 != null && !isoGridSquare1.getObjects().isEmpty()) {
                            IsoWorld.instance.CurrentCell.EnsureSurroundNotNull(isoGridSquare1.x, isoGridSquare1.y, int4);
                        }
                    }
                }
            }

            for (int int7 = 0; int7 < 8; int7++) {
                for (int int8 = 0; int8 < 50; int8++) {
                    IsoGridSquare isoGridSquare2 = ServerMap.instance.getGridSquare(int0 + int8, int1 + 0, int7);
                    if (isoGridSquare2 != null) {
                        isoGridSquare2.RecalcAllWithNeighbours(true);
                    }

                    isoGridSquare2 = ServerMap.instance.getGridSquare(int0 + int8, int3 - 1, int7);
                    if (isoGridSquare2 != null) {
                        isoGridSquare2.RecalcAllWithNeighbours(true);
                    }
                }

                for (int int9 = 0; int9 < 50; int9++) {
                    IsoGridSquare isoGridSquare3 = ServerMap.instance.getGridSquare(int0 + 0, int1 + int9, int7);
                    if (isoGridSquare3 != null) {
                        isoGridSquare3.RecalcAllWithNeighbours(true);
                    }

                    isoGridSquare3 = ServerMap.instance.getGridSquare(int2 - 1, int1 + int9, int7);
                    if (isoGridSquare3 != null) {
                        isoGridSquare3.RecalcAllWithNeighbours(true);
                    }
                }
            }

            byte _byte = 100;

            for (int int10 = 0; int10 < 5; int10++) {
                for (int int11 = 0; int11 < 5; int11++) {
                    IsoChunk isoChunk = this.chunks[int10][int11];
                    if (isoChunk != null) {
                        isoChunk.bLoaded = true;

                        for (int int12 = 0; int12 < _byte; int12++) {
                            for (int int13 = 0; int13 <= isoChunk.maxLevel; int13++) {
                                IsoGridSquare isoGridSquare4 = isoChunk.squares[int13][int12];
                                if (isoGridSquare4 != null) {
                                    if (isoGridSquare4.getRoom() != null && !isoGridSquare4.getRoom().def.bExplored) {
                                        this.UnexploredRooms.add(isoGridSquare4.getRoom().def);
                                    }

                                    isoGridSquare4.propertiesDirty = true;
                                }
                            }
                        }
                    }
                }
            }

            for (int int14 = 0; int14 < 5; int14++) {
                for (int int15 = 0; int15 < 5; int15++) {
                    if (this.chunks[int14][int15] != null) {
                        this.chunks[int14][int15].doLoadGridsquare();
                    }
                }
            }

            for (RoomDef roomDef1 : this.UnexploredRooms) {
                roomDef1.IndoorZombies++;
                if (roomDef1.IndoorZombies == 1) {
                    try {
                        zombie.VirtualZombieManager.instance.tryAddIndoorZombies(roomDef1, false);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                }
            }

            this.bLoaded = true;
        }

        public void Unload() {
            if (this.bLoaded) {
                if (ServerMap.MapLoading) {
                    DebugLog.log(
                        DebugType.MapLoading,
                        "Unloading cell: "
                            + this.WX
                            + ", "
                            + this.WY
                            + " ("
                            + ServerMap.instance.toWorldCellX(this.WX)
                            + ", "
                            + ServerMap.instance.toWorldCellX(this.WY)
                            + ")"
                    );
                }

                for (int int0 = 0; int0 < 5; int0++) {
                    for (int int1 = 0; int1 < 5; int1++) {
                        IsoChunk isoChunk = this.chunks[int0][int1];
                        if (isoChunk != null) {
                            isoChunk.removeFromWorld();
                            isoChunk.m_loadVehiclesObject = null;

                            for (int int2 = 0; int2 < isoChunk.vehicles.size(); int2++) {
                                BaseVehicle baseVehicle = (BaseVehicle)isoChunk.vehicles.get(int2);
                                VehiclesDB2.instance.updateVehicle(baseVehicle);
                            }

                            chunkLoader.addSaveUnloadedJob(isoChunk);
                            this.chunks[int0][int1] = null;
                        }
                    }
                }

                for (RoomDef roomDef : this.UnexploredRooms) {
                    if (roomDef.IndoorZombies == 1) {
                    }

                    roomDef.IndoorZombies--;
                }
            }
        }

        public void Save() {
            if (this.bLoaded) {
                for (int int0 = 0; int0 < 5; int0++) {
                    for (int int1 = 0; int1 < 5; int1++) {
                        IsoChunk isoChunk = this.chunks[int0][int1];
                        if (isoChunk != null) {
                            try {
                                chunkLoader.addSaveLoadedJob(isoChunk);

                                for (int int2 = 0; int2 < isoChunk.vehicles.size(); int2++) {
                                    BaseVehicle baseVehicle = (BaseVehicle)isoChunk.vehicles.get(int2);
                                    VehiclesDB2.instance.updateVehicle(baseVehicle);
                                }
                            } catch (Exception exception) {
                                exception.printStackTrace();
                                LoggerManager.getLogger("map").write(exception);
                            }
                        }
                    }
                }

                chunkLoader.updateSaved();
            }
        }

        public void update() {
            for (int int0 = 0; int0 < 5; int0++) {
                for (int int1 = 0; int1 < 5; int1++) {
                    IsoChunk isoChunk = this.chunks[int0][int1];
                    if (isoChunk != null) {
                        isoChunk.update();
                    }
                }
            }

            this.bPhysicsCheck = false;
        }

        public IsoChunk getChunk(int int1, int int0) {
            if (int1 >= 0 && int1 < 5 && int0 >= 0 && int0 < 5) {
                IsoChunk isoChunk = this.chunks[int1][int0];
                if (isoChunk != null) {
                    return isoChunk;
                }
            }

            return null;
        }

        public int getWX() {
            return this.WX;
        }

        public int getWY() {
            return this.WY;
        }
    }
}
